package org.chs.ts.batch.util;

import org.apache.commons.collections4.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Compay 盛唐天行
 * @Author: wuwei
 * @Censor By wuwei
 * @Sence 2022/12/26 14:03
 * @Modify 2022/12/26 14:03
 * @Description 转换类 支持 E -> R
 */
public class ConvertToUtil<E, R> {
    private static final Logger log = LoggerFactory.getLogger(ConvertToUtil.class);

    private static final Map<String, Object> excluedMap = new HashedMap<String, Object>() {{
        put("serialVersionUID", null);
        put("id", null);
        put("createBy", null);
        put("createTime", null);
        put("updateBy", null);
        put("updateTime", null);
        put("sysOrgCode", null);
    }};

    //private static final List<String> fieldListDefault = new ArrayList<String>(Arrays.asList("serialVersionUID"));


    /**
     * @param objTarget        目标类
     * @param objTrans         待转换类
     * @param excludeParameter 待转换类不具备类型
     * @return objTarget<E>
     */
    public static <E, R> E convertToV(E objTarget, R objTrans, Map<String, Object> excludeParameter) {

        //待转换类 字段属性
        Field[] fieldsTrans = objTrans.getClass().getDeclaredFields();
        Field[] fieldsTarget = objTarget.getClass().getDeclaredFields();

        for (Field field : fieldsTarget) {
            String attributeName = field.getName();
            if (excluedMap.containsKey(attributeName))
                continue;

            String methodName = attributeName.substring(0, 1).toUpperCase(Locale.ROOT) + attributeName.substring(1);
            Method setMethod = null;
            try {
                setMethod = objTarget.getClass().getMethod("set" + methodName, field.getType());

                //优先匹配 excludeParameter
                if (excludeParameter.containsKey(field.getName())) {

                    setMethod.invoke(
                            objTarget,
                            excludeParameter.get(field.getName()));
                    continue;
                }
            } catch (Exception e) {
                //e.printStackTrace();
                log.error(objTarget.getClass().getName() + " -> set" + methodName + " NoSuchMethodException!" + e.getMessage());
            }


            List<Field> fieldsTransTemp = Arrays.stream(fieldsTrans).filter(f -> f.getName().equals(attributeName)).collect(Collectors.toList());
            if (fieldsTransTemp.isEmpty()) {
                //log.info("method:convertToV "+objTarget.getClass().toString() +" convertTo "+objTrans.getClass().toString() +" attributeName:"+attributeName+" is not exists!");
                continue;
            }
            if (fieldsTransTemp.size() > 1) {
                log.info("method:convertToV " + objTarget.getClass() + " convertTo " + objTrans.getClass() + " attributeName:" + attributeName + " is multiple value!");
                continue;
            }
            Method getMethod;

            try {
                getMethod = objTrans.getClass().getMethod("get" + methodName);
                if (setMethod != null) {
                    setMethod.invoke(
                            objTarget,
                            getMethod.invoke(objTrans)
                    );
                }

            } catch (Exception e) {
                //e.printStackTrace();
                log.error(objTrans.getClass().getName() + " -> get" + methodName + " NoSuchMethodException!" + e.getMessage());
            }

        }

        return objTarget;
    }

    /**
     * 对象按照属性列表获取待打印信息
     */
    public static <E, R> String printObjectInfo(E obj, List<String> fieldList) {
        StringBuilder returnValue = new StringBuilder();
        Field[] fieldsTarget = obj.getClass().getDeclaredFields();
        boolean printAll = fieldList.isEmpty();
        //fieldList = fieldList.size() == 0 || fieldList == null ? fieldListDefault : fieldList;
        for (Field field : fieldsTarget) {

            if (excluedMap.containsKey(field.getName()))
                continue;
            // 判断 属性是否在当前结果集 中
            if (fieldList.stream().anyMatch(s -> s.equals(field.getName())) || printAll) {
                try {
                    Method getMethod = obj.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase(Locale.ROOT) + field.getName().substring(1));
                    Object temp_obj = getMethod.invoke(obj);
                    //returnValue.append(System.getProperty("line.separator"));
                    returnValue.append(field.getName()).append(":").append(temp_obj == null ? "null" : temp_obj.toString()).append("  ");
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {

                    //e.printStackTrace();
                    log.error(e.getMessage());
                } catch (Exception e) {
                    log.error(e.getMessage());
                }

            }
        }
        return returnValue.toString();

    }

    public static <E, R> String printObjectInfo(E obj, List<String> fieldList, boolean isUseExcluedMap) {
        StringBuilder returnValue = new StringBuilder();
        Field[] fieldsTarget = obj.getClass().getDeclaredFields();
        boolean printAll = fieldList.isEmpty();
        //fieldList = fieldList.size() == 0 || fieldList == null ? fieldListDefault : fieldList;
        for (Field field : fieldsTarget) {

            if (excluedMap.containsKey(field.getName()) && isUseExcluedMap)
                continue;
            // 判断 属性是否在当前结果集 中
            if (fieldList.stream().anyMatch(s -> s.equals(field.getName())) || printAll) {
                try {
                    Method getMethod = obj.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase(Locale.ROOT) + field.getName().substring(1));
                    Object temp_obj = getMethod.invoke(obj);
                    //returnValue.append(System.getProperty("line.separator"));
                    returnValue.append(field.getName()).append(":").append(temp_obj == null ? "null" : temp_obj.toString()).append("  ");
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {

                    //e.printStackTrace();
                    log.error(e.getMessage());
                } catch (Exception e) {
                    log.error(e.getMessage());
                }

            }
        }
        return returnValue.toString();

    }

    public static <E, R> String pringObjectInfo(List<E> objList, List<String> fieldList) {
        StringBuilder returnValue = new StringBuilder();
        boolean printAll = fieldList.isEmpty();

        for (E obj : objList) {
            Field[] fieldsTarget = obj.getClass().getDeclaredFields();
            for (Field field : fieldsTarget) {
                // 判断 属性是否在当前结果集 中
                if (fieldList.stream().anyMatch(s -> s.equals(field.getName())) || printAll) {
                    try {
                        Method getMethod = obj.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase(Locale.ROOT) + field.getName().substring(1));
                        Object temp_obj = getMethod.invoke(obj);
                        //returnValue.append(System.getProperty("line.separator"));
                        returnValue.append(field.getName()).append(":").append(temp_obj == null ? "null" : temp_obj.toString()).append("  ");
                    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {

                        //e.printStackTrace();
                        log.error(e.getMessage());
                    } catch (Exception e) {
                        log.error(e.getMessage());

                    }

                }
            }
        }
        return returnValue.toString();
    }

    public static String getRunningTime() {
        return getRunningTime("");
    }

    /**
     * @param startTime 开始时间
     * @return 返回耗时
     */
    public static String getRunningTime(String startTime) {
        if (!StringUtils.hasLength(startTime)) {
            return String.valueOf(System.currentTimeMillis());
        }

        return String.valueOf(System.currentTimeMillis() - Long.parseLong(startTime));
    }

    public static String timeMillisFormatDateTime(Long timeMillis) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timeMillis));
    }

    public static boolean isValidDate(String dataStr, String dateFormat) {
        boolean judgeresult = true;
        SimpleDateFormat format = new SimpleDateFormat(dateFormat);

        try {
            format.setLenient(false);
            format.parse(dataStr);
        } catch (ParseException e) {
            //e.printStackTrace();
            judgeresult = false;
        }
        return judgeresult;
    }


}
